package com.chenfan.mcn.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.mcn.annotations.ActionTracing;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.enums.IncomeContractTypeEnum;
import com.chenfan.mcn.enums.OperateLockEnum;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.mcn.extension.Res;
import com.chenfan.common.extension.validation.groups.Add;
import com.chenfan.common.extension.validation.groups.Modify;
import com.chenfan.common.extension.lock.DistributedLockTemplate;
import com.chenfan.mcn.model.IncomeContract;
import com.chenfan.mcn.model.McnPage;
import com.chenfan.mcn.model.dto.*;
import com.chenfan.mcn.model.vo.*;
import com.chenfan.mcn.service.IncomeContractService;
import com.chenfan.mcn.service.LiveCommodityService;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.mcn.extension.excel.ExcelUtils;
import com.chenfan.privilege.common.config.SearchAuthority;
import com.chenfan.privilege.common.config.UrlAuth;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;

/**
 * 收入合同
 * @author tangwei
 * Date:     2021/1/20 10:40
 * Description: 收入合同
 */
@Slf4j
@RestController
@RequestMapping("/incomeContract")
public class IncomeContractController {

    @Autowired
    private IncomeContractService incomeContractService;

    @Autowired
    private LiveCommodityService liveCommodityService;

    /**
     * 新增
     * @param incomeContractAddDTO
     * @return
     */
    @ActionTracing("新建")
    @PostMapping("/add")
    @UrlAuth({"revenueContract_add","intentionOrderList_addContract"})
    public Res<Long> addIncomeContract(@RequestBody @Validated({Add.class}) IncomeContractAddDTO incomeContractAddDTO) {
        return Res.ok(incomeContractService.addIncomeContract(incomeContractAddDTO));
    }

    /**
     * 编辑
     * @param incomeContractAddDTO
     * @return
     */
    @ActionTracing("编辑")
    @PostMapping("/update")
    public Res<Long> updateIncomeContract(@RequestBody @Validated({Modify.class}) IncomeContractAddDTO incomeContractAddDTO) {
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(incomeContractAddDTO.getId()),
                () -> Res.ok(incomeContractService.updateIncomeContract(incomeContractAddDTO)));
    }

    /**
     * 详情
     * @param id
     * @return
     */
    @GetMapping("/detail")
    public Res<IncomeContractDetailVO> incomeContractDetail(@RequestParam Long id) {
        return Res.ok(incomeContractService.incomeContractDetail(id));
    }

    /**
     * 根据合同ID获取合同类型
     * @param id
     * @return
     */
    @GetMapping("/getType")
    public Res<Integer> getType(@RequestParam Long id) {
        IncomeContract incomeContract = incomeContractService.selectById(id);
        BusinessAssert.notNull(incomeContract, McnErrorCode.INCOME_NOT_EXISTS);
        return Res.ok(incomeContract.getContractType());
    }


    /**
     * 收入合同列表(分页)
     * @param mcnPage
     * @param incomeContractSearchDTO
     * @return
     */
    @PostMapping("/getPage")
    @UrlAuth({"revenueContract_search"})
    public Res<Page<IncomeContractListVO>> getContractList(@ApiIgnore McnPage<IncomeContractListVO> mcnPage, @SearchAuthority IncomeContractSearchDTO incomeContractSearchDTO) {
        incomeContractSearchDTO.setSearcherId(UserVoContextHolder.getUserId());
        return Res.ok(incomeContractService.getContractPage(mcnPage, incomeContractSearchDTO));
    }

    /**
     * 收入合同列表(分页-无数据权限控制)
     * @param mcnPage
     * @param incomeContractSearchDTO
     * @return
     */
    @PostMapping("/unsecure/page")
    public Res<Page<IncomeContractListVO>> page(@ApiIgnore McnPage<IncomeContractListVO> mcnPage, @RequestBody IncomeContractSearchDTO incomeContractSearchDTO) {
        return Res.ok(incomeContractService.getContractPage(mcnPage, incomeContractSearchDTO));
    }

    /**
     * 收入合同列表-无数据权限控制
     * @param incomeContractSearchDTO
     * @return
     */
    @GetMapping("/getList")
    public Res<List<BasicContractVO>> getContractList(IncomeContractSearchDTO incomeContractSearchDTO) {
        return Res.ok(incomeContractService.getContractList(incomeContractSearchDTO));
    }

    /**
     * 导出收入合同列表
     * @param incomeContractSearchDTO
     * @param response
     */
    @ActionTracing("导出收入合同列表")
    @PostMapping("/export")
    @UrlAuth({"revenueContract_export"})
    public void exportContract(@SearchAuthority IncomeContractSearchDTO incomeContractSearchDTO, HttpServletResponse response) {
        StopWatch stopWatch = new StopWatch("导出收入合同");
        stopWatch.start("准备excel表格数据");
        List<IncomeContractExportVO> exportPage = CommonUtil.defaultList(incomeContractService.exportContract(incomeContractSearchDTO));
        stopWatch.stop();
        stopWatch.start("生成excel表格并响应");
        ExcelUtils.exportExcel(exportPage, "收入合同", IncomeContractExportVO.class, "收入合同.xlsx", response);
        stopWatch.stop();
        System.out.println(stopWatch.prettyPrint());
    }

    /**
     * 导出框架合同
     * @param incomeContractSearchDTO
     * @param response
     */
    @ActionTracing("导出框架合同")
    @PostMapping("/exportLiveContract")
    public void exportLiveContract(@SearchAuthority IncomeContractSearchDTO incomeContractSearchDTO, HttpServletResponse response) {
        StopWatch stopWatch = new StopWatch("导出框架合同");
        if(CollectionUtils.isEmpty(incomeContractSearchDTO.getContractType())) {
            incomeContractSearchDTO.setContractType(Lists.newArrayList(IncomeContractTypeEnum.LIVE_CONTRACT.getType()));
        }
        List<LiveContractExportVO> exportPage = null;
        if(incomeContractSearchDTO.getContractType().contains(IncomeContractTypeEnum.LIVE_CONTRACT.getType())) {
            incomeContractSearchDTO.setContractType(Lists.newArrayList(IncomeContractTypeEnum.LIVE_CONTRACT.getType()));
            stopWatch.start("准备excel表格数据");
            exportPage = incomeContractService.exportLiveContract(incomeContractSearchDTO);
            stopWatch.stop();
        }
        stopWatch.start("生成excel表格并响应");
        ExcelUtils.exportExcel(CommonUtil.defaultList(exportPage), "框架合同", LiveContractExportVO.class, "框架合同.xlsx", response);
        stopWatch.stop();
        System.out.println(stopWatch.prettyPrint());
    }

    /**
     * 导出收入合同补充协议
     * @param incomeContractSearchDTO
     * @param response
     */
    @ActionTracing("导出收入合同补充协议")
    @PostMapping("/exportAgreement")
    @UrlAuth({"revenueContract_export1"})
    public void exportAgreement(@SearchAuthority IncomeContractSearchDTO incomeContractSearchDTO, HttpServletResponse response) {
        List<IncomeContractAgreementExportVO> exportPage = CommonUtil.defaultList(incomeContractService.exportAgreement(incomeContractSearchDTO));
        ExcelUtils.exportExcel(exportPage, "收入合同补充协议", IncomeContractAgreementExportVO.class, "收入合同补充协议.xlsx", response);
    }


    /**
     * 变更收入合同状态
     *
     * @param incomeContractId {@link Long}
     * @param approvalStatus   {@link Integer}
     * @return {@link Res<Object>}
     */
    @ActionTracing("变更收入合同状态")
    @GetMapping(value = "/status/change")
    @UrlAuth({"revenueContract_withdraw","revenueContract_toVoid","revenueContract_submit"})
    public Res<Boolean> changeStatus(@RequestParam Long incomeContractId,
                                     @RequestParam Integer approvalStatus) {
        if (Objects.isNull(incomeContractId) || Objects.isNull(approvalStatus)) {
            throw new BusinessException(McnErrorCode.PARAM_ERROR);
        }
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(incomeContractId),
                () -> Res.ok(incomeContractService.changeStatus(incomeContractId, approvalStatus))
        );
    }


    /**
     * 获取收入合同编号
     *
     * @return {@link List<String>}
     */
    @GetMapping(value = "/getIncomeContractCode", produces = {"application/json;charset=UTF-8"})
    public Res<List<String>> getIncomeContractCode() {
        return Res.ok(incomeContractService.getIncomeContractCode());
    }

    /**
     * 客户关联的合同信息
     * @param mcnPage
     * @param customerId
     * @return
     */
    @GetMapping("/cusIncomeContract")
    public Res<Page<CusIncomeContractVO>> getCusContractInfo(@ApiIgnore McnPage<CusIncomeContractVO> mcnPage, @RequestParam Long customerId) {
        return Res.ok(incomeContractService.getCusContractInfo(mcnPage, customerId));
    }

    /**
     * 获取客户档案金额
     *
     * @param customerId {@link Long}
     * @return {@link CustomerFileAmount}
     */
    @GetMapping("/getCustomerFileAmount")
    public Res<CustomerFileAmount> getCustomerFileAmount(Long customerId) {
        return Res.ok(incomeContractService.getCustomerFileAmount(customerId));
    }

    /**
     * 获取列表合计金额（合同金额、回款金额、未回款金额）
     *
     * @param dto {@link IncomeAmountSumVO}
     * @return {@link Res<IncomeAmountSumVO>}
     */
    @PostMapping("/getSumAmount")
    public Res<IncomeAmountSumVO> getSumAmount(@SearchAuthority IncomeContractSearchDTO dto) {
        return Res.ok(incomeContractService.getSumAmount(dto));
    }

    /**
     * 法务审批（注：修改合同标签等数据）
     * @param dto
     * @return
     */
    @ActionTracing("法务审批")
    @PostMapping("/legalApproval")
    public Res<Boolean> legalApproval(@Validated @RequestBody IncomeContractLegalApprovalDTO dto) {
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(dto.getId()),
                () -> Res.ok(incomeContractService.legalApproval(dto)));
    }

    /**
     * 详情/编辑页-删除已录商品
     * @param id 商品主键ID
     * @return
     */
    @ActionTracing("执行单详情-删除已录商品")
    @GetMapping("/deleteLiveCommodity")
    public Res<Boolean> deleteLiveCommodity(@RequestParam Long id) {
        return Res.ok(liveCommodityService.releaseLiveContract(id));
    }

    /**
     * 直播合同详情页-添加商品
     * @param dto
     * @return
     */
    @ActionTracing("执行单详情-添加商品")
    @PostMapping("/addLiveCommodity")
    public Res<Boolean> addLiveCommodity(@Validated @RequestBody LiveContractAddCommodityDTO dto) {
        return Res.ok(liveCommodityService.addLiveCommodityFromContractDetail(dto));
    }


    /**
     * 查询待认领的直播合同
     * @param dto
     * @return
     */
    @PostMapping("/queryUnClaimLiveContract")
    @UrlAuth({"liveProductManagement_claim"})
    public Res<Page<LiveContractSelectVO>> queryUnClaimLiveContract(@Validated @RequestBody LiveContractQueryDto dto) {
        return Res.ok(incomeContractService.queryUnClaimLiveContract(dto));
    }

    /**
     * 变更业绩共享人
     * @param dto
     * @return
     */
    @ActionTracing("变更业绩共享人")
    @PostMapping("/updatePerformanceSharer")
    @UrlAuth({"revenueContract_performance"})
    public Res<Long> updatePerformanceSharer(@Validated @RequestBody PerformanceSharerUpdateDTO dto) {
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(dto.getIncomeContractId()),
                () -> Res.ok(incomeContractService.updatePerformanceSharer(dto)));
    }

    /**
     * 手动生成收入合同费
     * @param incomeContractId 收入合同ID
     * @return
     */
    @ActionTracing("手动生成收入合同费")
    @GetMapping("/regenerateIncomeFee/{incomeContractId}")
    @UrlAuth({"revenueContract_generate"})
    public Res<Long> regenerateIncomeFee(@PathVariable(name = "incomeContractId") Long incomeContractId) {
        Assert.notNull(incomeContractId, "收入合同ID不能为空");
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(incomeContractId),
                () -> Res.ok(incomeContractService.regenerateIncomeFee(incomeContractId)));
    }

    /**
     * 直播提成发放
     * @param id 收入合同id
     * @return
     */
    @ActionTracing("直播提成发放")
    @GetMapping("/distributeLiveCommission")
    public Res<Boolean> distributeLiveCommission(@RequestParam Long id) {
        return DistributedLockTemplate.execute(OperateLockEnum.INCOME_CONTRACT.generateKey(id),
                () -> Res.ok(incomeContractService.distributeLiveCommission(id)));
    }
}
